package com.mayflygeek.mayflyask.framework.webmvc;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
import org.springframework.web.context.ServletContextAware;

import com.mayflygeek.mayflyask.framework.webmvc.message.Flash;
import com.mayflygeek.mayflyask.framework.webmvc.message.FlashImpl;

/**
 * 
 * @author 虫虫
 * @team 蜉蝣极客
 * @link www.mayflygeek.com
 * @Emial chongchong@mayflygeek.com
 *
 */
public class Application implements ApplicationContextAware, ServletContextAware, DisposableBean {
	private static final Logger logger = LoggerFactory.getLogger(Application.class);
	private static final String ENSURE_INJECT_MESSAGE = "确保%s已注入Application，检查是否配置SpringApplicationFilter";
	private static ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<>();
	private static ThreadLocal<HttpServletResponse> responseHolder = new ThreadLocal<>();
	private static ApplicationContext applicationContext;
	private static ServletContext servletContext;

	/**
	 * 取得存储在静态变量中的spring ApplicationContext
	 * 
	 * @return
	 */
	public static ApplicationContext getApplicationContext() {
		checkApplicationContext();
		return applicationContext;
	}

	/**
	 * 获取指定类型的bean。如果有多个Bean是此类型，取第一个
	 * 
	 * @param requiredType
	 * @return
	 */
	public static <T> T getBean(Class<T> requiredType) {
		checkApplicationContext();
		return getApplicationContext().getBean(requiredType);
	}

	public static <T> List<T> getBeans(Class<T> requiredType) {
		checkApplicationContext();
		return new ArrayList<T>(getApplicationContext().getBeansOfType(requiredType).values());
	}

	/**
	 * 获取应用上下文名称
	 * 
	 * @return
	 */
	public static String getContextPath() {
		return getServletContext().getContextPath();
	}

	/**
	 * 获取flash对象
	 */
	public static Flash getFlash() {
		return getFlash(null);
	}

	public static Flash getFlash(Map<String, Object> container) {
		Flash flash = (Flash) getSession().getAttribute(Flash.FLASH_KEY);
		if (flash == null) {
			flash = makeFlash(container);
			getSession().setAttribute(Flash.FLASH_KEY, flash);
			logger.info("完成初始化flash");
		}
		return flash;
	}

	private static Flash makeFlash(Map<String, Object> container) {
		return (container == null) ? new FlashImpl() : new FlashImpl(container);
	}

	/**
	 * 获取地址
	 * 
	 * @param path
	 * @return
	 */
	public static String getRealPath(String path) {
		return getServletContext().getRealPath(path);
	}

	/**
	 * 获取当前HttpServletRequest
	 * 
	 * @return
	 */
	public static HttpServletRequest getRequest() {
		final HttpServletRequest request = requestHolder.get();
		Assert.notNull(request, String.format(ENSURE_INJECT_MESSAGE, "request"));
		return request;
	}

	/**
	 * 获取当前HttpServletResponse
	 * 
	 * @return
	 */
	public static HttpServletResponse getResponse() {
		final HttpServletResponse response = responseHolder.get();
		Assert.notNull(response, String.format(ENSURE_INJECT_MESSAGE, "response"));
		return response;
	}

	/**
	 * 获取存储在静态变量中的servletContext
	 * 
	 * @return
	 */
	public static ServletContext getServletContext() {
		checkServletContext();
		return servletContext;
	}

	/**
	 * 获取session
	 * 
	 * @return
	 */
	public static HttpSession getSession() {
		return getRequest().getSession();
	}

	public static void setRequestAndResponse(HttpServletRequest request, HttpServletResponse response) {
		requestHolder.set(request);
		responseHolder.set(response);
	}

	@Override
	public void destroy() throws Exception {
		cleanContexts();
	}

	@Override
	public void setServletContext(ServletContext servletContext) {
		Application.servletContext = servletContext;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		Application.applicationContext = applicationContext;
	}

	/**
	 * 清除applicationContext,servletContext静态变量
	 */
	public static void cleanContexts() {
		applicationContext = null;
		servletContext = null;
	}

	private static void checkApplicationContext() {
		if (applicationContext == null) {
			throw new IllegalStateException("applicationContext未注入，请将Application配置为Spring Bean");
		}
	}

	private static void checkServletContext() {
		if (servletContext == null) {
			throw new IllegalStateException("servletContext，请确认在web环境下获取");
		}
	}

}
